import {Meta} from '@storybook/addon-docs/blocks';

<Meta title="Guide/Pinia Store" />

# Pinia Store

For more details on why Pinia store is being adopted starting with OJS/OMP/OPS 3.5, check out our [Technical Roadmap](?path=/docs/guide-technical-roadmap--docs#pinia-stores-35)

## Pinia Store Gotchas

This is intentionally the first chapter to safe you some time!

When destructing state from the Pinia store, helpers must be used to avoid losing reactivity. Alternatively using the store directly without destructing is also good practice. Check the example in [Pinia documentation](https://pinia.vuejs.org/core-concepts/#Destructuring-from-a-Store).

## Component Pinia Store

The purpose of **Component Pinia Stores** is to contain business logic for individual **Pages**, **Complex Modals** and **Self-Contained Components**. Read more details on where to place business logic in [Page architecture](?path=/docs/guide-page-architecture--docs#where-to-place-business-logic).

The Pinia store has been extended with the following features:

- **Passing initial data**: Initial data can be passed when needed. That often might be configuration passed to the **Page** from PHP backend, or some props being passed to a **Complex Modal** or **Self-Contained Component**. It is important to note that only the first component (the topmost in hirearchy) is passing the configuration. Any other child component that's connecting to the store connects to it without passing the init state, as it has already been initialised.
- **Following Component Lifecycle**: It gets initialised when it's called in the first component. It tracks mount/unmount events and when all components using the store are unmounted it deletes its state. This is particularly useful when managing a **Complex Modal** as anytime it's closed its state will be removed. It gets initialised again the next time the modal is opened with new props.

These improvements are intended to make the developer experience very much the same as if we would define the business logic directly in the component, but still get the [benefits](../?path=/docs/guide-technical-roadmap--docs#pinia-stores-35) that come from using Pinia store.

Let's look for example how the component interacts with the store. A more advanced example can be found in [ExamplePage](?path=/docs/pages-example--docs).

```javascript
import {ref, computed} from 'vue';
import {defineComponentStore} from '@/utils/defineComponentStore';

export const useExamplePageStore = defineComponentStore(
	'examplePage',
	(props) => {
		const itemsPublishedCount = computed(() => {
			return props.items.filter((item) => item.status === 'published').length;
		});

		return {
			items: props.items,
			itemsPublishedCount,
		};
	},
);
```

```html
<template>
	<span>Published count: {{ store.itemsPublishedCount }}</span>
	<ul>
		<li v-for="item in store.items">{{ item.title}}</li>
	</ul>
</template>
<script setup>
	const props = defineProps({
		items: {
			type: Array,
			required: true,
		},
	});
	// when
	const store = useExamplePageStore(props);
</script>
```

### Observability and extensibility examples

To be added later. For now the best source is the official documentation [for plugins](https://pinia.vuejs.org/core-concepts/plugins.html).

## General Pinia Store

A couple of Pinia stores are also used for internal purposes, like managing announcements or dialogs. At this point these are not intended for direct interaction. There are dedicated composables for interacting with dialogs for example. The store purpose in these cases is to manage some global state.
